home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / zmdm_src / sz.c < prev    next >
C/C++ Source or Header  |  1988-06-26  |  30KB  |  1,548 lines

  1. /*
  2.  *                ACKNOWLEDGEMENTS
  3.  *
  4.  *    ZMDM was derived from rz/sz for Unix  posted by 
  5.  *    Chuck Forsberg (...!tektronix!reed!omen!caf ). We
  6.  *    thank him for his excellent code, and for giving
  7.  *    us permission to use and distribute his code and
  8.  *    documentation.
  9.  *
  10.  *    Atari St version by:
  11.  *        Jwahar Bammi
  12.  *            usenet: mandrill!bammi@{decvax,sun}.UUCP
  13.  *            csnet:  bammi@mandrill.ces.CWRU.edu
  14.  *            arpa:   bammi@mandrill.ces.CWRU.edu
  15.  *            CompuServe: 71515,155
  16.  */
  17.  
  18. #include "config.h"
  19. #define SVERSION "sz 1.23 01-15-87"
  20. #define SSTVERSION "sz 1.01 03-07-87"
  21. #define OS    "Unix V7/BSD"
  22.  
  23. #ifndef STANDALONE
  24. #define RETURN return
  25. #else
  26. int bibi() {} /* dummy */
  27. #endif 
  28.  
  29. /* #define SDEBUG */
  30.  
  31. /*
  32.  * sz.c By Chuck Forsberg
  33.  *
  34.  *    cc -O sz.c -o sz        USG (SYS III/V) Unix
  35.  *     cc -O -DV7  sz.c -o sz        Unix Version 7, 2.8 - 4.3 BSD
  36.  *
  37.  *        define CRCTABLE to use table driven CRC
  38.  *
  39.  *  ******* Some systems (Venix, Coherent, Regulus) do not *******
  40.  *  ******* support tty raw mode read(2) identically to    *******
  41.  *  ******* Unix. ONEREAD must be defined to force one     *******
  42.  *  ******* character reads for these systems.           *******
  43.  *
  44.  * A program for Unix to send files and commands to computers running
  45.  *  Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
  46.  *
  47.  *  Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
  48.  *
  49.  *  USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
  50.  *
  51.  *    St v 1.01
  52.  *        added support for 32 bit CRC's (Zmodem) ++jrb
  53.  *
  54.  */
  55.  
  56. #include "zmdm.h"
  57. #include "common.h"
  58. #include "zmodem.h"
  59.  
  60. #ifndef Vsync             /* Atari forgot these in osbind.h */
  61. #define Vsync()    xbios(37)
  62. #endif
  63.  
  64. #ifndef Supexec
  65.         /* Some versions of osbind don't define Supexec */
  66. #define Supexec(X) xbios(38,X)
  67. #endif
  68.  
  69. #define SLOGFILE "szlog"
  70.  
  71. #define purgeline()    while(Bconstat(1)) Bconin(1)
  72. #define S_IFDIR 0x0010
  73.  
  74. /*
  75.  * Attention string to be executed by receiver to interrupt streaming data
  76.  *  when an error is detected.  A pause (0336) may be needed before the
  77.  *  ^C (03) or after it.
  78.  */
  79. #ifdef READCHECK
  80. char Myattn[] = { 0 };
  81. #else
  82. #ifdef USG
  83. char Myattn[] = { 03, 0336, 0 };
  84. #else
  85. char Myattn[] = { 0 };
  86. #endif
  87. #endif
  88.  
  89. #if (MWC || MANX)
  90. FILE *fopen();
  91. #else
  92. FILE *fopen(), *fopenb();
  93. #endif
  94. static unsigned long SaveIntr;
  95. static int Resuming, ForceBin;
  96. static int in;
  97.  
  98. /* called by signal interrupt or terminate to clean things up */
  99. bibis(n)
  100. int n;
  101. {
  102.     canit(); flush_modem(); mode(0);
  103.     fprintf(STDERR, "\r\nsz: caught signal %d; exiting\n", n);
  104.  
  105.     aexit(128+n);
  106. }
  107.  
  108. /* Called when Zmodem gets an interrupt (^X) */
  109. #ifdef ONINTR
  110. onintr()
  111. {
  112.     siggi = 0;
  113.     longjmp(intrjmp, -1);
  114. }
  115. #endif
  116.  
  117. #define ZKER
  118. int Zctlesc;    /* Encode control characters */
  119.  
  120. #ifdef STANDALONE
  121. int main(argc, argv)
  122. #else
  123. int dosz(argc, argv)
  124. #endif
  125. int argc;
  126. char **argv;
  127. {
  128.     register char *cp;
  129.     register int npats;
  130.     int agcnt; char **agcv;
  131.     char **patts;
  132.  
  133. #ifdef STANDALONE
  134. #ifdef MWC
  135.     extern char *lmalloc();
  136. #endif
  137.  
  138.     /* Set up Dta */
  139.     Fsetdta(&statbuf);
  140.  
  141.     /* Get screen rez */
  142.     rez = Getrez();
  143.     drv_map = Drvmap();
  144.  
  145. #if (MWC || MANX)
  146. #ifndef DYNABUF
  147. #ifdef MWC
  148.     if((bufr = (unsigned char *)lmalloc((unsigned long)BBUFSIZ))
  149.                      == (unsigned char *)NULL)
  150. #else
  151.     if((bufr = (unsigned char *)Malloc((unsigned long)BBUFSIZ))
  152.                      == (unsigned char *)NULL)
  153. #endif
  154. #else
  155.     if((bufr = dalloc()) == (unsigned char *)NULL)
  156. #endif /* DYNABUF */
  157.     {
  158. #ifdef REMOTE
  159.         Bauxws("Sorry, could not allocate enough memory\r\n");
  160. #else
  161.         Bconws("Sorry, could not allocate enough memory\r\n");
  162. #endif
  163.  
  164.         Pterm(4);
  165.     }
  166. #else /* MWC || MANX */
  167. #ifdef DYNABUF
  168.     if((bufr = dalloc()) == (unsigned char *)NULL)
  169.     {
  170. #ifdef REMOTE
  171.         Bauxws("Sorry, could not allocate enough memory\r\n");
  172. #else
  173.         Bconws("Sorry, could not allocate enough memory\r\n");
  174. #endif
  175.         Pterm(5);
  176.     }
  177. #endif /* DYNABUF */
  178. #endif /* MWC || MANX */
  179.  
  180. #ifndef REMOTE
  181.     STDERR = stderr;
  182. #else
  183. #ifndef DLIBS
  184.     if((STDERR = fopen("aux:", "rw")) == (FILE *)NULL)
  185.     {
  186.         Bauxws("Could not Open Aux Stream for Stderr\r\n");
  187.         finish();
  188.     }
  189.     setbuf(STDERR, (char *)NULL);
  190. #else
  191.     STDERR = stdaux;
  192. #endif /* DLIBS */
  193.     
  194. #endif /* REMOTE */
  195.     {
  196.         int speed;
  197.         speed = getbaud();
  198.         Baudrate = BAUD_RATE(speed);
  199.         SetIoBuf();
  200.         Rsconf(speed, 0,-1,-1,-1,-1);
  201.         Vsync(); Vsync();
  202.     }
  203. #endif /* STANDALONE */
  204.  
  205.     SendType = 1;
  206.     Rxtimeout = 600;
  207.     npats=0;
  208.     if (argc<2)
  209.     {
  210.         susage();
  211.         RETURN(1);
  212.     }
  213.  
  214.     initz();
  215. #ifndef STANDALONE
  216.     schkinvok(argv[0]);
  217. #else
  218.     Progname = "sz";
  219. #endif
  220.  
  221.     SaveIntr = Setexc(0x0102, -1L);
  222.     BusErr   = Setexc(2, -1L);
  223.     AddrErr  = Setexc(3, -1L);
  224.  
  225.     Verbose = 0;
  226.     Resuming = FALSE;
  227.     ForceBin = FALSE;
  228.     in = (-1);
  229.     vdebug = 0;
  230.  
  231. #ifdef SDEBUG
  232.     logf = (FILE *)NULL;
  233. #endif
  234.     while (--argc) {
  235.         cp = *++argv;
  236.         if (*cp++ == '-' && *cp) {
  237.             while ( *cp) {
  238.                 switch(*cp++) {
  239.                 case '+':
  240.                     Lzmanag = ZMAPND; break;
  241. #ifdef CSTOPB
  242.                 case '2':
  243.                     Twostop = TRUE; break;
  244. #endif
  245.                 case '7':
  246.                     Wcsmask=0177; break;
  247.  
  248. /*
  249.     On the St we look up the ext and decide. For Xmodem
  250.     transfers, the file is always sent in binary mode
  251.     and it is the responsibility of the receiver to
  252.     strip CR if so desired.
  253.                 case 'a':
  254.                     Lzconv = ZCNL;
  255.                     Ascii = TRUE; break;
  256.                 case 'b':
  257.                     Lzconv = ZCBIN; break;
  258. */
  259.  
  260. /*  ST extention, force binary, useful to back up every thing
  261.  *  in image mode, see -B option of rz too +jrb
  262.  */
  263.                 case 'B':
  264.                     ForceBin = TRUE;
  265.                     Lzconv = ZCBIN;
  266.                     break;
  267.                 case 'C':
  268.                     if (--argc < 1) {
  269.                         susage();
  270.                         RETURN(1);
  271.                     }
  272.                     Cmdtries = atoi(*++argv);
  273.                     break;
  274.                 case 'i':
  275.                     Cmdack1 = ZCACK1;
  276.                     /* **** FALL THROUGH TO **** */
  277.                 case 'c':
  278.                     if (--argc != 1) {
  279.                         susage();
  280.                         RETURN(1);
  281.                     }
  282.                     Command = TRUE;
  283.                     Cmdstr = *++argv;
  284.                     break;
  285.                 case 'd':
  286.                     ++Dottoslash;
  287.                     /* **** FALL THROUGH TO **** */
  288.                 case 'f':
  289.                     Fullname=TRUE; break;
  290.                 case 'E':
  291.                     Zctlesc = (-1); break;
  292.                 case 'e':
  293.                     Zctlesc = 1; break;
  294.                 case 'k':
  295.                     Blklen=KSIZE; break;
  296.                 case 'L':
  297.                     if (--argc < 1) {
  298.                         susage();
  299.                         RETURN(1);
  300.                     }
  301.                     blkopt = atoi(*++argv);
  302.                     if (blkopt<32 || blkopt>1024)
  303.                     {
  304.                         susage();
  305.                         RETURN(1);
  306.                     }
  307.                     break;
  308.                 case 'l':
  309.                     if (--argc < 1) {
  310.                         susage();
  311.                         RETURN(1);
  312.                     }
  313.                     Tframlen = atoi(*++argv);
  314.                     if (Tframlen<32 || Tframlen>1024)
  315.                     {
  316.                         susage();
  317.                         RETURN(1);
  318.                     }
  319.                     break;
  320.                 case 'N':
  321.                     Lzmanag = ZMDIFF;  break;
  322.                 case 'n':
  323.                     Lzmanag = ZMNEW;  break;
  324.                 case 'o':
  325.                     Wantfcs32 = FALSE; break;
  326.                 case 'p':
  327.                     Lzmanag = ZMPROT;  break;
  328.                 case 'r':
  329.                     Lzconv = ZCRESUM; Resuming = TRUE; break;
  330.                 case 'q':
  331.                     Quiet=TRUE; Verbose=0; break;
  332.                 case 't':
  333.                     if (--argc < 1) {
  334.                         susage();
  335.                         RETURN(1);
  336.                     }
  337.                     Rxtimeout = atoi(*++argv);
  338.                     if (Rxtimeout<10 || Rxtimeout>1000)
  339.                     {
  340.                         susage();
  341.                         RETURN(1);
  342.                     }
  343.                     break;
  344. #ifdef TESTATTN
  345.                 case 'T':
  346.                     Testattn = TRUE; break;
  347. #endif
  348.                 case 'u':
  349.                     ++Unlinkafter; break;
  350.                 case 'v':
  351.                     ++Verbose; break;
  352.                 case 'X':
  353.                     ++Modem; break;
  354.                 case 'y':
  355.                     Lzmanag = ZMCLOB; break;
  356.                 default:
  357.                     susage();
  358.                     RETURN(1);
  359.                 }
  360.             }
  361.         }
  362.         else if ( !npats && argc>0) {
  363.             if (argv[0][0]) {
  364.                 npats=argc;
  365.                 patts=argv;
  366.             }
  367.         }
  368.     }
  369.     if (npats < 1 && !Command) 
  370.     {
  371.         susage();
  372.         RETURN(1);
  373.     }
  374.  
  375. #ifdef SDEBUG
  376.     if (Verbose > 2)
  377.     {
  378.         if ((logf = fopen(SLOGFILE, "a"))== (FILE *)NULL)
  379.         {
  380.             fprintf(STDERR, "Can't open log file %s\n",SLOGFILE);
  381.             RETURN(0200);
  382.         }
  383.         fprintf(logf, "Progname=%s\n", Progname);
  384.         vdebug = 1;
  385.         fflush(logf);
  386.     }
  387. #endif
  388.  
  389.     if ( !Quiet)
  390.     {
  391.         if (Verbose < 2)
  392.             Verbose = 2;
  393.     }
  394.  
  395.  
  396.     Setexc(0x0102, bibis);
  397.     Setexc(2, buserr);
  398.     Setexc(3, addrerr);
  399.  
  400.     if(setjmp(busjmp))
  401.     {
  402.         /* On a bus error - instead of 2 bombs */
  403.         fprintf(STDERR,"\r\nFATAL: Bus Error\n\n");
  404. #ifdef SDEBUG
  405.         if(logf != (FILE *)NULL)
  406.             fclose(logf);
  407. #endif
  408.         if(in != -1)
  409.         {
  410.             stfclose(in);
  411.             in = (-1);
  412.         }
  413.         canit();
  414.         Setexc(2, BusErr);
  415.         Setexc(3, AddrErr);
  416.         Setexc(0x0102, SaveIntr);
  417.         RETURN(2);
  418.     }
  419.  
  420.     if(setjmp(addrjmp))
  421.     {
  422.         /* On address error - instead of 3 bombs */
  423.         fprintf(STDERR,"\r\nFATAL: Address Error\n\n");
  424. #ifdef SDEBUG
  425.         if(logf != (FILE *)NULL)
  426.             fclose(logf);
  427. #endif
  428.         if(in != -1)
  429.         {
  430.             stfclose(in);
  431.             in = (-1);
  432.         }
  433.         canit();
  434.         Setexc(2, BusErr);
  435.         Setexc(3, AddrErr);
  436.         Setexc(0x0102, SaveIntr);
  437.         RETURN(3);
  438.     }
  439.  
  440.     if((Exitcode = setjmp(abrtjmp)))
  441.     {
  442.         fprintf(STDERR,"\nTransfer ABORT\n\n");
  443. #ifdef SDEBUG
  444.     if(logf != (FILE *)NULL)
  445.         fclose(logf);
  446. #endif
  447.         if(in != -1)
  448.         {
  449.             stfclose(in);
  450.             in = (-1);
  451.         }
  452.         Setexc(2, BusErr);
  453.         Setexc(3, AddrErr);
  454.         Setexc(0x0102, SaveIntr);
  455.         RETURN(Exitcode);
  456.     }
  457.  
  458.     mode(1);
  459.  
  460.  
  461.     if ( !Modem) {
  462.         if (!Command && !Quiet && Verbose != 1)
  463.         {
  464.             fprintf(STDERR, "sz: %d file%s requested:\n",
  465.                 npats, npats>1?"s":"");
  466.             for ( agcnt=npats, agcv=patts; --agcnt>=0; )
  467.             {
  468.                 fprintf(STDERR, "%s ", *agcv++);
  469.             }
  470.             fprintf(STDERR, "\n\n");
  471.  
  472. #ifdef SDEBUG
  473.             if(Verbose > 2)
  474.             {
  475.                 fprintf(logf, "sz: %d file%s requested:\n",
  476.                     npats, npats>1?"s":"");
  477.                 for ( agcnt=npats, agcv=patts; --agcnt>=0; )
  478.                 {
  479.                     fprintf(logf, "%s ", *agcv++);
  480.                 }
  481.                 fprintf(logf, "\n");
  482.                 fflush(logf);
  483.             }
  484. #endif
  485.         }
  486.         if (!Nozmodem) {
  487.             stohdr(0L);
  488.             if (Command)
  489.                 Txhdr[ZF0] = ZCOMMAND;
  490.             zshhdr(ZRQINIT, Txhdr);
  491.         }
  492.     }
  493.     flush_modem();
  494.  
  495.     if (Command) {
  496.         if (getzrxinit()) {
  497.             Exitcode=0200; canit();
  498.         }
  499.         else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
  500.             Exitcode=0200; canit();
  501.         }
  502.     } else if (wcsend(npats, patts)==ERROR) {
  503.         Exitcode=0200;
  504.         canit();
  505.     }
  506.     flush_modem();
  507.     mode(0);
  508.  
  509. #ifdef SDEBUG
  510.     if(logf != (FILE *)NULL)
  511.         fclose(logf);
  512. #endif
  513.     if(in != -1)
  514.     {
  515.         fclose(in);
  516.         in = (-1);
  517.     }
  518.  
  519.     putc('\n', STDERR);
  520.     Setexc(2, BusErr);
  521.     Setexc(3, AddrErr);
  522.     Setexc(0x0102, SaveIntr);
  523.     RETURN((errcnt != 0) | Exitcode);
  524.  
  525. }
  526.  
  527. #ifdef STANDALONE
  528. RETURN(n)
  529. int n;
  530. {
  531.     ResetIoBuf();
  532. #if (MWC || MANX)
  533. #ifndef DYNABUF
  534.     free(bufr);
  535. #else
  536.     Mfree(bufr);
  537. #endif
  538. #else
  539. #ifdef DYNABUF
  540.     Mfree(bufr);
  541. #endif
  542. #endif
  543.     exit(n);
  544. }
  545. #endif /* STANDALONE */
  546.  
  547. wcsend(argc, argp)
  548. char *argp[];
  549. {
  550.     register int n;
  551.  
  552.     Crcflg=FALSE;
  553.     Firstsec=TRUE;
  554.     for (n=0; n<argc; ++n) {
  555.         Totsecs = 0;
  556.         if (wcs(argp[n])==ERROR)
  557.             return ERROR;
  558.     }
  559.     Totsecs = 0;
  560.     if (Filcnt==0) {    /* bitch if we couldn't open ANY files */
  561.         if (1) {
  562.             Command = TRUE;
  563.             Cmdstr = "echo \"sz: Can't open any requested files\"";
  564.             if (getzrxinit()) {
  565.                 Exitcode=0200; canit();
  566.             }
  567.             else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr))) {
  568.                 Exitcode=0200; canit();
  569.             }
  570.             Exitcode = 1; return OK;
  571.         }
  572.         canit();
  573.         fprintf(STDERR,"\n\nCan't open any requested files.\n\n");
  574.         return ERROR;
  575.     }
  576.     if (Zmodem)
  577.         saybibi();
  578.     else
  579.         wctxpn("");
  580.     return OK;
  581. }
  582.  
  583. wcs(oname)
  584. char *oname;
  585. {
  586.     extern struct stat statbuf;
  587.     char name[PATHLEN];
  588.  
  589.     strcpy(name, oname);
  590.     ++Noeofseen;  Lastread = 0;  Lastc = (-1); Dontread = FALSE;
  591.  
  592.     /* Check for directory or block special files */
  593.     if(Fsfirst(name,(int)(0x01 | 0x010 | 0x020)) != 0)
  594.     {
  595.         ++errcnt;
  596.         return OK;    /* may be others */
  597.     }
  598.  
  599.     if (statbuf.st_mode & S_IFDIR ) {
  600.         return OK;
  601.     }
  602.  
  603.     if((in = stfopen(oname,"r")) <= 0){
  604.         ++errcnt;
  605.         return OK;    /* pass over it, there may be others */
  606.     }
  607.  
  608.     ++Filcnt;
  609.     switch (wctxpn(name)) {
  610.     case ERROR:
  611.         return ERROR;
  612.     case ZSKIP:
  613.         return OK;
  614.     }
  615.     if (!Zmodem && wctx()==ERROR)
  616.         return ERROR;
  617.     if (Unlinkafter)
  618.         unlink(oname);
  619.     return 0;
  620. }
  621.  
  622. #define ISDRIVE(X) ( (((X >= 'a') && (X <= 'n'))) || ((X >= 'A') && (X <= 'N')))
  623. /*
  624.  * generate and transmit pathname block consisting of
  625.  *  pathname (null terminated),
  626.  *  file length, mode time and file mode in octal
  627.  *  as provided by the St's Fsfirst() call.
  628.  *  N.B.: modifies the passed name, may extend it!
  629.  */
  630. wctxpn(name)
  631. char *name;
  632. {
  633.     register char *p, *q;
  634.     char name2[PATHLEN];
  635.     unsigned long unixtime;
  636.     extern struct stat statbuf;
  637.     extern unsigned long st2unix();    /* Convert St's date and time to unix
  638.                    time (seconds since Jan 1 1970 00:00:00) */
  639.  
  640.     if(*name)
  641.         if(Fsfirst(name,(int)(0x01 | 0x020)) != 0)
  642.             return ERROR;
  643.  
  644.     if (Modem) {
  645. #ifndef REMOTE
  646.         if (*name) {
  647.             fprintf(STDERR,
  648.             "Outgoing:\n\t Name: %s\n\t Size: %ld Bytes\n\
  649. \tBlocks: %ld\n\tBufSize: %ld\n\n",
  650.               name, statbuf.st_size, statbuf.st_size>>7, (long)BBUFSIZ);
  651.         }
  652. #endif /* REMOTE */
  653.         return OK;
  654.     }
  655.  
  656.     vfile2("\r\nAwaiting pathname nak for %s\r\n", *name?name:"<END>");
  657.  
  658.     if ( !Zmodem)
  659.         if (getnak())
  660.             return ERROR;
  661.  
  662.     /* convert to Unix style path names */
  663.     /* skip any device identifier */
  664.     if(ISDRIVE(name[0]) && (name[1] == ':'))
  665.         name = &name[2];
  666.  
  667.     for(p = name; *p != '\0'; p++)
  668.     {
  669.         if(*p == '\\')
  670.             *p = '/';
  671.     }
  672.  
  673.     if(!Resuming)
  674.     {
  675.         if(ForceBin)
  676.         {
  677.             Lzconv = ZCBIN;
  678.             Ascii = FALSE;
  679.         }
  680.         else
  681.         {
  682.             if(!isbinary(name))
  683.             {
  684.                 /* We indicate to the other side */
  685.                 Lzconv = ZCNL;
  686.                 Ascii = TRUE;
  687.             }
  688.             else
  689.             {
  690.                 Lzconv = ZCBIN;
  691.                 Ascii = FALSE;
  692.             }
  693.         }
  694.     }
  695.  
  696.     q = (char *) 0;
  697.     if (Dottoslash) {        /* change . to . */
  698.         for (p=name; *p; ++p) {
  699.             if (*p == '/')
  700.                 q = p;
  701.             else if (*p == '.')
  702.                 *(q=p) = '/';
  703.         }
  704.         if (q && strlen(++q) > 8) {    /* If name>8 chars */
  705.             q += 8;            /*   make it .ext */
  706.             strcpy(name2, q);    /* save excess of name */
  707.             *q = '.';
  708.             strcpy(++q, name2);    /* add it back */
  709.         }
  710.     }
  711.  
  712.     for (p=name, q=secbuf ; *p; )
  713.         if ((*q++ = *p++) == '/' && !Fullname)
  714.             q = secbuf;
  715.     *q++ = 0;
  716.     p=q;
  717.     while (q < (secbuf + KSIZE))
  718.         *q++ = 0;
  719.     if (*name)
  720.     {
  721.         unixtime = st2unix(statbuf.st_time, statbuf.st_date);
  722.         sprintf(p, "%lu %lo %o", statbuf.st_size,
  723.             unixtime,
  724.              ((statbuf.st_mode & 0x01)?0444:0644));
  725.     }
  726.  
  727.     if(Verbose)
  728. #ifndef REMOTE
  729.         fprintf(STDERR,
  730. "Outgoing: [Hit CTRL-C to Cancel]\n\tName: %s\n\tSize: %ld Bytes\n\tBufSize:\
  731.  %ld\n",
  732.             name, statbuf.st_size, (long)BBUFSIZ);
  733.     if(!Resuming)
  734.     {
  735.         fprintf(STDERR,"\tMode: %s\n\n", (Ascii)?"ASCII":"BINARY");
  736.     }
  737.     else
  738.     {
  739.         fprintf(STDERR,"\tMode: Resume Transfer Mode\n\n");
  740.     }
  741. #endif
  742.  
  743. #ifdef SDEBUG
  744.     if(Verbose > 2)
  745.     {
  746.         fprintf(STDERR,"File: %s (%s)\n", name, p);
  747.         fprintf(logf,"File: %s (%s)\n", name, p);
  748.         fflush(logf);
  749.     }
  750. #endif
  751.  
  752.     /* force 1k blocks if name won't fit in 128 byte block */
  753.     if (secbuf[125])
  754.         Blklen=KSIZE;
  755.     else {        /* A little goodie for IMP/KMD */
  756.         if (Zmodem)
  757.             Blklen = SECSIZ;
  758.         secbuf[127] = (statbuf.st_size + 127) >>7;
  759.         secbuf[126] = (statbuf.st_size + 127) >>15;
  760.     }
  761.     if (Zmodem)
  762.         return zsendfile(secbuf, (int)(1+strlen(p)+ 
  763.                 (int)((long)p-(long)secbuf)), statbuf.st_size);
  764.     if (wcputsec(secbuf, 0, SECSIZ)==ERROR)
  765.         return ERROR;
  766.     return OK;
  767. }
  768.  
  769. getnak()
  770. {
  771.     register int firstch;
  772.  
  773.     Lastrx = 0;
  774.     for (;;) {
  775.         switch (firstch = readock(800,1)) {
  776.         case ZPAD:
  777.             if (getzrxinit())
  778.                 return ERROR;
  779.             Ascii = 0;
  780.             return FALSE;
  781.         case TIMEOUT:
  782.             vfile("Timeout on pathname\n");
  783.             return TRUE;
  784.         case WANTG:
  785. #ifdef USG
  786.             mode(2);    /* Set cbreak, XON/XOFF, etc. */
  787. #endif
  788.             Optiong = TRUE;
  789.             Blklen=KSIZE;
  790.         case WANTCRC:
  791.             Crcflg = TRUE;
  792.         case NAK:
  793.             return FALSE;
  794.         case CAN:
  795.             if ((firstch = readock(20,1)) == CAN && Lastrx == CAN)
  796.                 return TRUE;
  797.         default:
  798.             break;
  799.         }
  800.         Lastrx = firstch;
  801.     }
  802. }
  803.  
  804.  
  805. wctx()
  806. {
  807.     register int sectnum, attempts, firstch;
  808.  
  809.     Firstsec=TRUE;
  810.  
  811.     while ((firstch=readock(Rxtimeout, 2))!=NAK && firstch != WANTCRC
  812.       && firstch != WANTG && firstch!=TIMEOUT && firstch!=CAN)
  813.         ;
  814.     if (firstch==CAN) {
  815.         fprintf(STDERR, "\r\nReceiver CANcelled\n");
  816.         return ERROR;
  817.     }
  818.     if (firstch==WANTCRC)
  819.         Crcflg=TRUE;
  820.     if (firstch==WANTG)
  821.         Crcflg=TRUE;
  822.     sectnum=1;
  823.     while (filbuf(secbuf, Blklen)) {
  824.         if (wcputsec(secbuf, sectnum, Blklen)==ERROR) {
  825.             return ERROR;
  826.         } else
  827.             sectnum++;
  828.     }
  829.  
  830. #ifndef REMOTE
  831.     if (Verbose>1)
  832.     {
  833.         fprintf(STDERR, "\nClosing\n\n");
  834. #ifdef SDEBUG
  835.         if(Verbose > 2)
  836.         {
  837.             fprintf(logf, " Closing\n");
  838.             fflush(logf);
  839.         }
  840. #endif
  841.     }
  842. #endif /* REMOTE */
  843.  
  844.     stfclose(in);
  845.     in = (-1);
  846.  
  847.     attempts=0;
  848.     do {
  849.         vfile(" EOT ");
  850.         purgeline();
  851.         sendline(EOT);
  852.         flush_modem();
  853.         ++attempts;
  854.     }
  855.         while ((firstch=(readock(Rxtimeout, 1)) != ACK) && attempts < RETRYMAX);
  856.     if (attempts == RETRYMAX) {
  857.         fprintf(STDERR, "\r\nNo ACK on EOT\n");
  858.         return ERROR;
  859.     }
  860.     else
  861.         return OK;
  862. }
  863.  
  864. wcputsec(buf, sectnum, cseclen)
  865. char *buf;
  866. int sectnum;
  867. int cseclen;    /* data length of this sector to send */
  868. {
  869.     register int checksum, wcj;
  870.     register char *cp;
  871.     unsigned int oldcrc;
  872.     int firstch;
  873.     int attempts;
  874.  
  875.     firstch=0;    /* part of logic to detect CAN CAN */
  876.  
  877. #ifndef REMOTE
  878.     if (Verbose>1)
  879.     {
  880.         fprintf(STDERR, "\rBlock %06d  %04dK ", Totsecs, (Totsecs>>3));
  881. #ifdef SDEBUG
  882.         if(Verbose > 2)
  883.         {
  884.             fprintf(logf, "\rBlock %d %dK ", Totsecs, (Totsecs>>3) );
  885.             fflush(logf);
  886.         }
  887. #endif
  888.     }
  889. #endif /* REMOTE */
  890.  
  891.     for (attempts=0; attempts <= RETRYMAX; attempts++) {
  892.         Lastrx= firstch;
  893.         sendline(cseclen==KSIZE?STX:SOH);
  894.         sendline(sectnum);
  895.         sendline(-sectnum -1);
  896.         oldcrc=checksum=0;
  897.         for (wcj=cseclen,cp=buf; --wcj>=0; ) {
  898.             sendline(*cp);
  899.             oldcrc=updcrc((0377& *cp), oldcrc);
  900.             checksum += *cp++;
  901.         }
  902.         if (Crcflg) {
  903.             oldcrc=updcrc(0,updcrc(0,oldcrc));
  904.             sendline((int)oldcrc>>8);
  905.             sendline((int)oldcrc);
  906.         }
  907.         else
  908.             sendline(checksum);
  909.  
  910.         if (Optiong) {
  911.             Firstsec = FALSE; return OK;
  912.         }
  913.         firstch = readock(Rxtimeout, (Noeofseen&§num) ? 2:1);
  914. gotnak:
  915.         switch (firstch) {
  916.         case CAN:
  917.             if(Lastrx == CAN) {
  918. cancan:
  919.                 fprintf(STDERR, "\r\nCancelled\n");  return ERROR;
  920.             }
  921.             break;
  922.         case TIMEOUT:
  923.             vfile("Timeout on sector ACK\n"); continue;
  924.         case WANTCRC:
  925.             if (Firstsec)
  926.                 Crcflg = TRUE;
  927.         case NAK:
  928.             vfile("NAK on sector\n"); continue;
  929.         case ACK: 
  930.             Firstsec=FALSE;
  931.             Totsecs += (cseclen>>7);
  932.             return OK;
  933.         case ERROR:
  934.             vfile("Got burst for sector ACK\n"); break;
  935.         default:
  936.             vfile("Got %02x for sector ACK\n", firstch); break;
  937.         }
  938.         for (;;) {
  939.             Lastrx = firstch;
  940.             if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT)
  941.                 break;
  942.             if (firstch == NAK || firstch == WANTCRC)
  943.                 goto gotnak;
  944.             if (firstch == CAN && Lastrx == CAN)
  945.                 goto cancan;
  946.         }
  947.     }
  948.     fprintf(STDERR, "\r\nRetry Count Exceeded\n");
  949.     return ERROR;
  950. }
  951.  
  952. /* fill buf with count chars padding with ^Z for CPM */
  953. filbuf(buf, count)
  954. register unsigned char *buf;
  955. register int count;
  956. {
  957.     register int m;
  958.  
  959.     if((buf[0] = stgetc(in)) == EOF)
  960.         return 0;
  961.  
  962.     for(m = 1; (m < count) && ((buf[m] = stgetc(in)) != EOF); m++)
  963.         /* loop */ ;
  964.  
  965.     while (m < count)
  966.         buf[m++] = 032;
  967.  
  968.     return count;
  969.  
  970. }
  971. /* fill buf with count chars */
  972. zfilbuf(buf, count)
  973. register char *buf;
  974. {
  975.     register int c, m;
  976.  
  977.     m=count;
  978.     while ((c=stgetc(in))!=EOF) {
  979.         *buf++ =c;
  980.         if (--m == 0)
  981.             break;
  982.     }
  983.     return (count - m);
  984. }
  985.  
  986. /*
  987.  * readock(timeout, count) reads character(s) from file descriptor 0
  988.  *  (1 <= count <= 3)
  989.  * it attempts to read count characters. If it gets more than one,
  990.  * it is an error unless all are CAN
  991.  * (otherwise, only normal response is ACK, CAN, or C)
  992.  *  Only looks for one if Optiong, which signifies cbreak, not raw input
  993.  *
  994.  * timeout is in tenths of seconds
  995.  */
  996. readock(timeout, count)
  997. int timeout, count;
  998. {
  999.     register int c;
  1000.     static char byt[5];
  1001.  
  1002.     if (Optiong)
  1003.         count = 1;    /* Special hack for cbreak */
  1004.  
  1005.     if (setjmp(tohere)) {
  1006.         vfile("TIMEOUT\n");
  1007.         return TIMEOUT;
  1008.     }
  1009.     c = timeout >> 3;
  1010.     if (c<2)
  1011.         c=2;
  1012. #ifdef SDEBUG
  1013.     if (Verbose>3) {
  1014.         fprintf(STDERR, "Timeout=%d Calling alarm(%d) ", timeout, c);
  1015.         byt[1] = 0;
  1016.         fprintf(logf, "Timeout=%d Calling alarm(%d) ", timeout, c);
  1017.         fflush(logf);
  1018.  
  1019.     }
  1020. #endif
  1021.     stalarm(c);
  1022.     c=read_modem(byt, count);
  1023.  
  1024.     stalarm(0);
  1025. #ifdef SDEBUG
  1026.     if (Verbose>5)
  1027.     {
  1028.         fprintf(STDERR, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);
  1029.         fprintf(logf, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);
  1030.         fflush(logf);
  1031.     }
  1032. #endif
  1033.  
  1034.     if (c<1)
  1035.         return TIMEOUT;
  1036.     if (c==1)
  1037.         return (byt[0]&0377);
  1038.     else
  1039.         while (c)
  1040.             if (byt[--c] != CAN)
  1041.                 return ERROR;
  1042.     return CAN;
  1043. }
  1044.  
  1045. sreadline(n)
  1046. {
  1047.     return (readock(n, 1));
  1048. }
  1049.  
  1050.  
  1051. susage()
  1052. {
  1053.     fprintf(STDERR,"\nSend file(s) with ZMODEM/YMODEM/XMODEM Protocol\n");
  1054.     fprintf(STDERR,"    (Y) = Option applies to YMODEM only\n");
  1055.     fprintf(STDERR,"    (Z) = Option applies to ZMODEM only\n");
  1056.     fprintf(STDERR,
  1057.     "%s for %s by ST Enthusiasts at Case Western Reserve University\n",
  1058.        SSTVERSION, STOS);
  1059.     fprintf(STDERR,"\tBased on %s for %s by Chuck Forsberg\n\n", SVERSION, OS);
  1060. /*    fprintf(STDERR,"Usage:    sz [-12+adefknquvXy] [-] file ...\n"); */
  1061.     fprintf(STDERR,"Usage:    sz [-+defknquvXyB] file ...\n");
  1062. /*    fprintf(STDERR,"    sz [-1eqv] -c COMMAND\n"); */
  1063.     fprintf(STDERR,"    sz [-eqv] -c COMMAND\n");
  1064. /*    fprintf(STDERR,"    1 Use stdout for modem input\n"); */
  1065. #ifdef CSTOPB
  1066.     fprintf(STDERR,"    2 Use 2 stop bits\n");
  1067. #endif
  1068.     fprintf(STDERR,"    + Append to existing destination file (Z)\n");
  1069. /*    fprintf(STDERR,"    a (ASCII) change NL to CR/LF\n"); */
  1070.     fprintf(STDERR,"    c send COMMAND (Z)\n");
  1071.     fprintf(STDERR,"    d Change '.' to '/' in pathnames (Y/Z)\n");
  1072.     fprintf(STDERR,"    e Escape control characters (Z)\n");
  1073.     fprintf(STDERR,"    f send Full pathname (Y/Z)\n");
  1074.     fprintf(STDERR,"    i send COMMAND, ack Immediately (Z)\n");
  1075.     fprintf(STDERR,"    k Send 1024 byte packets (Y)\n");
  1076.     fprintf(STDERR,"    L N Limit packet length to N bytes (Z)\n");
  1077.     fprintf(STDERR,"    l N Limit frame length to N bytes (l>=L) (Z)\n");
  1078.     fprintf(STDERR,"    n send file if Newer|longer (Z)\n");
  1079.     fprintf(STDERR,"    N send file if different length|date (Z)\n");
  1080.     fprintf(STDERR, "    o Use 16 bit CRC instead of 32 bit CRC (Z)\n");
  1081.     fprintf(STDERR,"    p Protect existing destination file (Z)\n");
  1082.     fprintf(STDERR,"    r Resume/Recover interrupted file transfer (Z)\n");
  1083.     fprintf(STDERR,"    q Quiet (no progress reports)\n");
  1084.     fprintf(STDERR,"    u Unlink file after transmission\n");
  1085.     fprintf(STDERR,"    v Verbose - debugging information\n");
  1086.     fprintf(STDERR,"    X XMODEM protocol - send no pathnames\n");
  1087.     fprintf(STDERR,"    y Yes, overwrite existing file (Z)\n");
  1088.     fprintf(STDERR,"    B Force Binary mode transfers (Z)\n");
  1089. /*    fprintf(STDERR,
  1090. "- as pathname sends standard input as sPID.sz or environment ONAME\n"); */
  1091.     return(1);
  1092. }
  1093.  
  1094. /*
  1095.  * Get the receiver's init parameters
  1096.  */
  1097. getzrxinit()
  1098. {
  1099.     register int n;
  1100.  
  1101.     for (n=10; --n>=0; ) {
  1102.         
  1103.         switch (zgethdr(Rxhdr, 1)) {
  1104.         case ZCHALLENGE:    /* Echo receiver's challenge numbr */
  1105.             stohdr(Rxpos);
  1106.             zshhdr(ZACK, Txhdr);
  1107.             continue;
  1108.         case ZCOMMAND:        /* They didn't see out ZRQINIT */
  1109.             stohdr(0L);
  1110.             zshhdr(ZRQINIT, Txhdr);
  1111.             continue;
  1112.         case ZRINIT:
  1113.             Rxflags = 0377 & Rxhdr[ZF0];
  1114.              Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
  1115.  
  1116.             Rxbuflen = (0337 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1])<<8);
  1117.             vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
  1118.             siggi = 0;
  1119. #ifndef READCHECK
  1120. #ifdef USG
  1121.             mode(2);    /* Set cbreak, XON/XOFF, etc. */
  1122. #else
  1123.             /* Use 1024 byte frames if no sample/interrupt */
  1124.             if (Rxbuflen < 32 || Rxbuflen > 1024) {
  1125.                 Rxbuflen = 1024;
  1126.                 vfile("Rxbuflen=%d", Rxbuflen);
  1127.             }
  1128. #endif
  1129. #endif
  1130.             /* Override to force shorter frame length */
  1131.             if (Rxbuflen && (Rxbuflen>Tframlen) && (Tframlen>=32))
  1132.                 Rxbuflen = Tframlen;
  1133.             if ( !Rxbuflen && (Tframlen>=32) && (Tframlen<=1024))
  1134.                 Rxbuflen = Tframlen;
  1135.             vfile("Rxbuflen=%d", Rxbuflen);
  1136.  
  1137.             /*
  1138.              * If input is not a regular file, force ACK's each 1024
  1139.              *  (A smarter strategey could be used here ...)
  1140.              */
  1141.             if ((Rxbuflen == 0) || (Rxbuflen > 1024))
  1142.                 Rxbuflen = 1024;
  1143.             vfile("Rxbuflen=%d", Rxbuflen);
  1144.  
  1145.             return (sendzsinit());
  1146.         case ZCAN:
  1147.         case TIMEOUT:
  1148.             return ERROR;
  1149.         case ZRQINIT:
  1150.             if (Rxhdr[ZF0] == ZCOMMAND)
  1151.                 continue;
  1152.         default:
  1153.             zshhdr(ZNAK, Txhdr);
  1154.             continue;
  1155.         }
  1156.     }
  1157.     return ERROR;
  1158. }
  1159.  
  1160. /* Send send-init information */
  1161. sendzsinit()
  1162. {
  1163.     register int c;
  1164.     register int errors;
  1165.  
  1166.     if (Myattn[0] == '\0')
  1167.         return OK;
  1168.  
  1169.     errors = 0;
  1170.     for (;;) {
  1171.         stohdr(0L);
  1172.         zsbhdr(ZSINIT, Txhdr);
  1173.         zsdata(Myattn, 1+strlen(Myattn), ZCRCW);
  1174.         c = zgethdr(Rxhdr, 1);
  1175.         switch (c) {
  1176.         case ZCAN:
  1177.             return ERROR;
  1178.         case ZACK:
  1179.             return OK;
  1180.         default:
  1181.             if (++errors > 9)
  1182.                 return ERROR;
  1183.             continue;
  1184.         }
  1185.     }
  1186. }
  1187.  
  1188. /* Send file name and related info */
  1189. zsendfile(buf, blen, szbytes)
  1190. char *buf;
  1191. int blen;
  1192. long szbytes;
  1193. {
  1194.     register int c, szstat;
  1195.     long start_time, end_time;
  1196.     extern void rd_time();
  1197.  
  1198.     Supexec(rd_time);
  1199.     start_time = pr_time;
  1200.     
  1201.     for (;;) {
  1202.         Txhdr[ZF0] = Lzconv;    /* file conversion request */
  1203.         Txhdr[ZF1] = Lzmanag;    /* file management request */
  1204.         Txhdr[ZF2] = Lztrans;    /* file transport request */
  1205.         Txhdr[ZF3] = 0;
  1206.         zsbhdr(ZFILE, Txhdr);
  1207.         zsdata(buf, blen, ZCRCW);
  1208. again:
  1209.         c = zgethdr(Rxhdr, 1);
  1210.         switch (c) {
  1211.         case ZRINIT:
  1212.             goto again;
  1213.         case ZCAN:
  1214.         case TIMEOUT:
  1215.         case ZABORT:
  1216.         case ZFIN:
  1217.             return ERROR;
  1218.         case ZSKIP:
  1219. #ifndef REMOTE
  1220.             fprintf(STDERR,"\n\n");
  1221. #endif
  1222.             stfclose(in); in = (-1); return c;
  1223.         case ZRPOS:
  1224.             if(stfseek(in, Rxpos, 0))
  1225.             {
  1226.                 fprintf(STDERR,"\r\nError While Seeking file\n");
  1227.                 return ERROR;
  1228.             }
  1229.             Txpos = Rxpos; Lastc = (-1); Dontread = FALSE;
  1230.             if((szstat =  zsendfdata()) == OK)
  1231.             {
  1232. #ifndef REMOTE
  1233.                 Supexec(rd_time);
  1234.                 end_time = pr_time;
  1235.                 fprintf(STDERR,"%ld Bytes Sent\t\
  1236. Transfer Time %ld secs.\tApprox %ld cps\n\n", szbytes, (end_time - start_time)/200L,
  1237. szbytes/((end_time - start_time)/200L));
  1238. #endif
  1239.             }
  1240.             return szstat;
  1241.         case ERROR:
  1242.         default:
  1243.             continue;
  1244.         }
  1245.     }
  1246. }
  1247.  
  1248. /* Send the data in the file */
  1249. zsendfdata()
  1250. {
  1251.     register int c, c1, e;
  1252.     register int newcnt;
  1253.     register long tcount = 0;
  1254.     static int tleft = 6;    /* Counter for test mode */
  1255.     
  1256.     if (Baudrate > 300)
  1257.         Blklen = 256;
  1258.     if (Baudrate > 2400)
  1259.         Blklen = KSIZE;
  1260. /*    if (Rxbuflen && Blklen>Rxbuflen)  --jrb do not limit block size */
  1261.     if (Rxbuflen)
  1262.         Blklen = Rxbuflen;
  1263.     if (blkopt && Blklen > blkopt)
  1264.         Blklen = blkopt;
  1265.     vfile("Rxbuflen=%d Blklen=%d", Rxbuflen, Blklen);
  1266. somemore:
  1267.     if (setjmp(intrjmp)) {
  1268. waitack:
  1269.         switch (c1 = getinsync()) {
  1270.         default:
  1271.         case ZCAN:
  1272.             fprintf(STDERR,"\r\nReceiver Cancelled Transfer\n\n");
  1273.             stfclose(in);
  1274.             in = (-1);
  1275.             return ERROR;
  1276.         case ZSKIP:
  1277. #ifndef REMOTE
  1278.             fprintf(STDERR,"\r\nReceiver forced SKIP Transfer(1)\n\n");
  1279. #endif
  1280.             stfclose(in);
  1281.             in = (-1);
  1282.             return c1;
  1283.         case ZACK:
  1284.             tcount += c;
  1285.             lreport(tcount);
  1286.             /* fall thru */
  1287.         case ZRPOS:
  1288.             break;
  1289.         case ZRINIT:
  1290.             return OK;
  1291.         }
  1292.     }
  1293.  
  1294.     siggi = 1;
  1295.     newcnt = Rxbuflen;
  1296.     stohdr(Txpos);
  1297.     zsbhdr(ZDATA, Txhdr);
  1298.  
  1299.     /*
  1300.      * Special testing mode.  This should force receiver to Attn,ZRPOS
  1301.      *  many times.  Each time the signal should be caught, causing the
  1302.      *  file to be started over from the beginning.
  1303.      */
  1304. #ifdef TESTATTN
  1305.     if (Testattn) {
  1306.         if ( --tleft)
  1307.             while (tcount < 20000) {
  1308.                 wr_modem(qbf);
  1309.                 tcount += strlen(qbf);
  1310. #ifdef READCHECK
  1311.                 while (Bconstat(1)) {
  1312.                     switch (sreadline(1)) {
  1313.                     case CAN:
  1314.                     case ZPAD:
  1315.                         goto waitack;
  1316.                     }
  1317.                 }
  1318. #endif
  1319.             }
  1320.         siggi = 0; canit();
  1321.         stsleep(3); purgeline(); mode(0);
  1322. #ifdef SDEBUG
  1323.         if(logf != (FILE *)NULL)
  1324.             fclose(logf);
  1325. #endif
  1326.  
  1327. /*        printf("\nsz: Tcount = %ld\n", tcount); */
  1328.         if (tleft) {
  1329.             /* printf("\r\nERROR: Interrupts Not Caught\n"); */
  1330.             aexit(1);
  1331.         }
  1332.         aexit(0);
  1333.     }
  1334. #endif
  1335.  
  1336.     do {
  1337.         if (Dontread) {
  1338.             c = Lastc;
  1339.         } else {
  1340.             c = zfilbuf(secbuf, Blklen);
  1341.             Lastread = Txpos;  Lastc = c;
  1342.         }
  1343. #ifdef SDEBUG
  1344.         if (Verbose > 10)
  1345.             vfile("Dontread=%d c=%d", Dontread, c);
  1346. #endif
  1347.  
  1348.         Dontread = FALSE;
  1349.         if (c < Blklen)
  1350.             e = ZCRCE;
  1351.         else if (Rxbuflen && (newcnt -= c) <= 0)
  1352.             e = ZCRCW;
  1353.         else
  1354.             e = ZCRCG;
  1355.         zsdata(secbuf, c, e);
  1356.         Txpos += c;
  1357.         if(e == ZCRCG)
  1358.         {
  1359.             tcount += c;
  1360.             lreport(tcount);
  1361.         }
  1362.  
  1363.         if (e == ZCRCW)
  1364.             goto waitack;
  1365. #ifdef READCHECK
  1366.         /*
  1367.          * If the reverse channel can be tested for data,
  1368.          *  this logic may be used to detect error packets
  1369.          *  sent by the receiver, in place of setjmp/longjmp
  1370.          *  rdchk(fdes) returns non 0 if a character is available
  1371.          */
  1372.         flush_modem();
  1373.         while (Bconstat(1)) {
  1374.             switch (sreadline(1)) {
  1375.             case CAN:
  1376.             case ZPAD:
  1377.                 zsdata(secbuf, 0, ZCRCE);
  1378.                 goto waitack;
  1379.             }
  1380.         }
  1381. #endif
  1382.     } while (c == Blklen);
  1383.     tcount += c;
  1384.     lreport(tcount);
  1385.     siggi = 0;
  1386.     lsct = 1;
  1387.  
  1388.     for (;;) {
  1389.         stohdr(Txpos);
  1390.         zsbhdr(ZEOF, Txhdr);
  1391.         switch (getinsync()) {
  1392.         case ZACK:
  1393.             continue;
  1394.         case ZRPOS:
  1395.             goto somemore;
  1396.         case ZRINIT:
  1397.             return OK;
  1398.         case ZSKIP:
  1399. #ifndef REMOTE
  1400.             fprintf(STDERR,"\r\nReceiver forced SKIP Transfer(2)\n\n");
  1401. #endif
  1402.             stfclose(in);
  1403.             in = (-1);
  1404.             return c;
  1405.         default:
  1406.             fprintf(STDERR,"\r\nErrors while Send Data\n\n");
  1407.             stfclose(in);
  1408.             in = (-1);
  1409.             return ERROR;
  1410.         }
  1411.     }
  1412. }
  1413.  
  1414. /*
  1415.  * Respond to receiver's complaint, get back in sync with receiver
  1416.  */
  1417. getinsync()
  1418. {
  1419.     register int c;
  1420.  
  1421.     for (;;) {
  1422. #ifdef TESTATTN
  1423.         if (Testattn) {
  1424.             wr_modem("\r\n\n\n***** Signal Caught *****\r\n");
  1425.             Rxpos = 0; c = ZRPOS;
  1426.         } else
  1427. #endif
  1428.  
  1429.             c = zgethdr(Rxhdr, 0);
  1430.         switch (c) {
  1431.         case ZCAN:
  1432.         case ZABORT:
  1433.         case ZFIN:
  1434.         case TIMEOUT:
  1435.             return ERROR;
  1436.         case ZRPOS:
  1437.             if (Lastc >= 0 && Lastread == Rxpos) {
  1438.                 Dontread = TRUE;
  1439.             } else {
  1440.                 /* clearerr(in); */    /* In case file EOF seen */
  1441.                 if(stfseek(in, Rxpos, 0))
  1442.                 {
  1443.                     fprintf(STDERR,"\r\nError While Seeking file\n");
  1444.                     return ERROR;
  1445.                 }
  1446.  
  1447.             }
  1448.             Txpos = Rxpos;
  1449.             return c;
  1450.         case ZACK:
  1451.             return c;
  1452.         case ZRINIT:
  1453.         case ZSKIP:
  1454. #ifndef REMOTE
  1455.             fprintf(STDERR,"\n\n");
  1456. #endif
  1457.             stfclose(in);
  1458.             in = (-1);
  1459.             return c;
  1460.         case ERROR:
  1461.         default:
  1462.             zsbhdr(ZNAK, Txhdr);
  1463.             continue;
  1464.         }
  1465.     }
  1466. }
  1467. /* Say "bibi" to the receiver, try to do it cleanly */
  1468. saybibi()
  1469. {
  1470.     for (;;) {
  1471.         stohdr(0L);
  1472.         zsbhdr(ZFIN, Txhdr);
  1473.         switch (zgethdr(Rxhdr, 0)) {
  1474.         case ZFIN:
  1475.             sendline('O'); sendline('O'); flush_modem();
  1476.         case ZCAN:
  1477.         case TIMEOUT:
  1478.             return;
  1479.         }
  1480.     }
  1481. }
  1482.  
  1483. /* Send command and related info */
  1484. zsendcmd(buf, blen)
  1485. char *buf;
  1486. {
  1487.     register int c, errors;
  1488.     long cmdnum;
  1489.  
  1490. /*    cmdnum = getpid(); */
  1491.     cmdnum = 1;    /* A random # */
  1492.     errors = 0;
  1493.     for (;;) {
  1494.         stohdr(cmdnum);
  1495.         Txhdr[ZF0] = Cmdack1;
  1496.         zsbhdr(ZCOMMAND, Txhdr);
  1497.         zsdata(buf, blen, ZCRCW);
  1498. listen:
  1499.         Rxtimeout = 100;        /* Ten second wait for resp. */
  1500.         c = zgethdr(Rxhdr, 1);
  1501.  
  1502.         switch (c) {
  1503.         case ZRINIT:
  1504.             continue;
  1505.         case ERROR:
  1506.         case TIMEOUT:
  1507.             if (++errors > Cmdtries)
  1508.                 return ERROR;
  1509.             continue;
  1510.         case ZCAN:
  1511.         case ZABORT:
  1512.         case ZFIN:
  1513.         case ZSKIP:
  1514.         case ZRPOS:
  1515.             return ERROR;
  1516.         default:
  1517.             if (++errors > 10)
  1518.                 return ERROR;
  1519.             continue;
  1520.         case ZCOMPL:
  1521.             Exitcode = Rxpos;
  1522.             saybibi();
  1523.             return OK;
  1524.         case ZRQINIT:
  1525.             vfile("******** RZ *******");
  1526. /*            stsystem("rz"); */
  1527.             vfile("******** SZ *******");
  1528.             goto listen;
  1529.         }
  1530.     }
  1531. }
  1532.  
  1533.  
  1534. #ifndef STANDALONE
  1535. /*
  1536.  * If called as sb use YMODEM protocol
  1537.  */
  1538. schkinvok(s)
  1539. char *s;
  1540. {
  1541.     if (s[0]=='s' && s[1]=='b') {
  1542.         Nozmodem = TRUE; Blklen=KSIZE;
  1543.     }
  1544. }
  1545. #endif
  1546.  
  1547. /* -eof- */
  1548.